package cn.aylog.simpleStack;

import java.util.Stack;

/**
 * 计算器底层实现 之
 *  中缀表达式
 *  计算 1+2+3+4*5 = 26
 */
public class CaculatorDemo2 {
    public static void main(String[] args) {
        String express = "1+2+3+4*5-6/2-7-8-9+100";
        Calculator calculator = new Calculator();
        double res = calculator.calc(express);
        System.out.printf("%s=%f", express, res);
    }
}

class Calculator {

    public double calc(String express) {
        // 表达式的有效性校验
        boolean flag = express.matches("^\\d+([ ]*[*/+-]?[ ]*\\d+)+?$");
        if(!flag) {
            System.out.println("无效的表达式~");
            return 0;
        }
        // 数据存储栈
        Stack<Double> numberStack = new Stack<>();
        Stack<Character> operStack = new Stack<>();

        int len = express.length();
        String temp = "";
        for(int i=0; i<len; i++) {
            char ch = express.charAt(i);
            if(isOperator(ch)) {
                // 运算符栈为空, 直接入栈
                if(operStack.isEmpty()) {
                    operStack.push(ch);
                } else {
                    // 根据优先级处理
                    if(getPriority(ch) >= getPriority(operStack.peek())) {
                        // 优先级高, 直接入栈
                        operStack.push(ch);
                    } else {
                        // 当前运算符优先级低, 先运算栈内的有限级高的运算
                        double num1 = numberStack.pop();
                        double num2 = numberStack.pop();
                        char oper = operStack.pop();
                        double res = this._calc(num1, num2, oper);
                        numberStack.push(res);
                        operStack.push(ch);
                    }
                }
            } else {
                temp += ch;
                // 数值保存
                if((i+1 < len) && isOperator(express.charAt(i+1)) || (i+1 == len) ) {
                    double res = dealSub(temp.trim(), operStack);
                    numberStack.push(res);
                    temp = "";
                }
            }
        }

        while (!operStack.isEmpty()) {
            double res = this._calc(numberStack.pop(), numberStack.pop(), operStack.pop());
            numberStack.push(res);
        }

        return numberStack.pop();
    }

    /**
     * 获取运算符的优先级
     */
    private int getPriority(int ch) {
        if(ch == '+' || ch == '-') {
            return 1;
        } else if(ch == '*' || ch == '/') {
            return 2;
        } else {
            return 0;
        }
    }

    /**
     * 数据计算
     */
    private double _calc(double num1, double num2, int ch) {
        double ret = 0d;
        switch (ch) {
            case '+':
                ret = num1 + num2;
                break;
            case '-':
                ret = num2 - num1;
                break;
            case '*':
                ret = num1 * num2;
                break;
            case '/':
                ret = num2 / num1;
                break;
        }
        return ret;
    }

    /**
     * 判断当前字符是否为运算符
     */
    private boolean isOperator(int ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }

    /**
     * 处理减法的数据, 将减法换成加法
     */
    private double dealSub(String nStr, Stack<Character> operStack) {
        Double num = Double.parseDouble(nStr);
        if(operStack.isEmpty()) {
            return num;
        }
        if(operStack.peek() == '-') {
            num *= -1;
            // 减法变加法
            operStack.pop();
            operStack.push('+');
        }
        return num;
    }
}
